package com.android.monee.domain;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.joda.time.DateTime;
import org.joda.time.DateTimeComparator;
import org.joda.time.Months;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;

import com.android.monee.data.model.Mensuality;

public class MensGrp implements Comparable<MensGrp>, Cloneable, Collection<Mensuality>{

	protected DateTime date;
	protected List<Mensuality> mensualities;
	
	public MensGrp(Collection<BudgetService> budgets, DateTime date){
		this.date = date;
		this.mensualities = new ArrayList<Mensuality>();	
		
		for(BudgetService budget : budgets){
			if(budget.hasMensualities() && budget.hasMensualityForDate(date))
				this.mensualities.add(budget.getMens(date));
		}
	}
	
	public MensGrp(Date date, Collection<Mensuality> mensualities){
		this.date = new DateTime(date);
		this.mensualities = new ArrayList<Mensuality>();
		this.mensualities.addAll(mensualities);
	}
	
	public MensGrp (MensGrp mensGrp){
		this.date = new DateTime(mensGrp.getDate());
		this.mensualities = new ArrayList<Mensuality>();
		this.mensualities.addAll(mensGrp);
	}
	

	
	
	public float getProvAmount(){
		float sum = 0;
		for(Mensuality mens : this.mensualities){
			sum += mens.isDone() ? mens.getAmount() : 0;
		}
		return sum;
	}
	
	public float getNotProvAmount(){
		return getTotalAmount()-getProvAmount();
	}
	
	public float getTotalAmount(){
		float sum = 0;
		for(Mensuality mens : this.mensualities){
			sum += mens.getAmount();
		}
		return sum;
	}
	
	public int getNbDone(){
		int nbDone = 0;
		for(Mensuality mens : this){
			if(mens.isDone())
				nbDone++;
		}
		return nbDone;
	}
	
	public boolean areAllDone(){
		return getNbDone() == size();
	}
	
	public boolean  areAnyDone(){
		return getNbDone() == 0;
	}
	
	public void sort(){
		Collections.sort(this.mensualities);
	}
	
	public void sort(Comparator<Mensuality> comp){
		Collections.sort(this.mensualities, comp);
	}
	
	public Date getDate() {
		return date.toDate();
	}
		
	public boolean add(Mensuality object) {
		return mensualities.add(object);
	}
	
	public Mensuality get(int location) {
		return mensualities.get(location);
	}

	public int size() {
		return mensualities.size();
	}

	@Override
	public int compareTo(MensGrp another) {
		return this.date.toDate().compareTo(another.getDate());
	}

	@Override
	public Iterator<Mensuality> iterator() {
		return (Iterator<Mensuality>) this.mensualities.iterator();
	}
	
	public void add(int location, Mensuality object) {
		mensualities.add(location, object);
	}

	@Override
	public boolean addAll(Collection<? extends Mensuality> arg0) {
		return mensualities.addAll(arg0);
	}
	
	public void clear() {
		mensualities.clear();
	}

	public boolean contains(Object object) {
		return mensualities.contains(object);
	}

	public boolean containsAll(Collection<?> arg0) {
		return mensualities.containsAll(arg0);
	}

	public boolean equals(Object object) {
		return mensualities.equals(object);
	}

	public boolean isEmpty() {
		return mensualities.isEmpty();
	}

	public boolean remove(Object object) {
		return mensualities.remove(object);
	}

	public boolean removeAll(Collection<?> arg0) {
		return mensualities.removeAll(arg0);
	}

	public boolean retainAll(Collection<?> arg0) {
		return mensualities.retainAll(arg0);
	}

	public Object[] toArray() {
		return mensualities.toArray();
	}

	public <T> T[] toArray(T[] array) {
		return mensualities.toArray(array);
	}

	public Object clone(){
		MensGrp clone = null;
		try {
			clone = (MensGrp) super.clone();
			clone.date = (DateTime) new DateTime(this.date);
			clone.mensualities = new ArrayList<Mensuality>();
			
			for(Mensuality mens : this.mensualities){
				clone.mensualities.add((Mensuality) mens.clone());
			}
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return clone;
	}
	
	public enum MensGrpType {ALL, DONE, UNDONE};
	
	public static List<MensGrp> calcMensGrps (MensGrpType type){
		List<Mensuality> mensualities = new ArrayList<Mensuality>();
		
		switch(type){
		case DONE:
			mensualities.addAll(MensualityService.getDoneMensualities());
			break;
		case UNDONE:
			mensualities.addAll(MensualityService.calcNextMensualities());
			break;
		case ALL:
			mensualities.addAll(MensualityService.getDoneMensualities());
			mensualities.addAll(MensualityService.calcNextMensualities());
			break;
		}
		
		return toMensGrps(mensualities);
	}
	
	public static List<MensGrp> calcMensGroups(List<BudgetService> budgets){
		List<MensGrp> mensGroups = new ArrayList<MensGrp>();
		//System.out.println("Calc mens groups");
		for(DateTime date : BudgetService.calcMonthDifferenceBetweenMensualities(budgets)){
			//System.out.println("\tDate of group : "+date.toString());
			MensGrp grp = new MensGrp(budgets, date);
			mensGroups.add(grp);
//			for(Mensuality mens : grp){
//				System.out.println("\t\tMens of grp : "+mens.getBudgetId()+" "+mens.isDone()+" "+mens.getDate().toString());
//			}
		}
		return mensGroups;
	}

	//TODO : suppr cette méthode et utiliser la version 2 (juste au dessus)
	public static List<MensGrp> toMensGrps (List<Mensuality> mensualities){
		Map<Date, MensGrp> map = new HashMap<Date, MensGrp>();
		
		for(Mensuality mens : mensualities){
			if(map.containsKey(mens.getDate())){
				MensGrp mensGroup = map.get(mens.getDate());
				mensGroup.add(mens);
			}
			else{
				MensGrp mensGroup = new MensGrp(mens.getDate(), new ArrayList<Mensuality>());
				mensGroup.add(mens);
				map.put(mensGroup.getDate(), mensGroup);
			}
		}
		
		List<MensGrp> mensGroups = new ArrayList<MensGrp>(map.values());
		Collections.sort(mensGroups);
		
		return mensGroups;
	}
		
	public static List<Mensuality> toMensList (List<MensGrp> mensGrps){
		List<Mensuality> mensualities = new ArrayList<Mensuality>();
		for(MensGrp mensGrp : mensGrps){
			mensualities.addAll(mensGrp);
		}
		
		return mensualities;
	}
}
